#include "list.h"
#include "interrupt.h"

void list_init(struct list* l){
    l->head.prev = NULL;
    l->tail.next = NULL;

    l->head.next = &l->tail;
    l->tail.prev = &l->head;
}

void list_insert_before(struct list_elem* l1, struct list_elem* l2){
    enum intr_status _old_status = intr_disable();

    l1->prev->next = l2;
    l2->prev = l1->prev;
    l2->next = l1;
    l1->prev = l2;

    intr_set_status(_old_status);
}

void list_remove(struct list_elem* pelem){
    enum intr_status _old_status = intr_disable();

    pelem->prev->next = pelem->next;
    pelem->next->prev = pelem->prev;

    intr_set_status(_old_status);
}

void list_push(struct list* plist, struct list_elem* elem){
    list_insert_before(plist->head.next, elem);
}

struct list_elem* list_pop(struct list* plist){
    struct list_elem* _e = plist->head.next;
    list_remove(plist->head.next);
    return _e;
}

void list_append(struct list* plist, struct list_elem* elem){
    list_insert_before(&plist->tail, elem);
}

bool list_empty(struct list* plist){
    return (plist->head.next == &plist->tail ? true : false);
}

uint32_t list_len(struct list* plist){
    uint32_t _list_cnt = 0;
    struct list_elem* _e = plist->head.next;

    for(; _e != &plist->tail; _e = _e->next, _list_cnt++);

    return _list_cnt;
}

struct list_elem* list_traversal(struct list* plist, function func, int arg){
    struct list_elem* _e = plist->head.next;
    if(list_empty(plist))
        return NULL;

    for(; _e != &plist->tail; _e = _e->next){
        if(func(_e, arg))
            return _e;
    }

    return NULL;
}

bool elem_find(struct list* plist, struct list_elem* obj_elem){
    struct list_elem* _e = plist->head.next;

    for(; _e != &plist->tail; _e = _e->next){
        if(_e == obj_elem)
            return true;
    }

    return false;
}

